package com.gdufe.firesafe.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gdufe.firesafe.dao.DeviceDao;
import com.gdufe.firesafe.exception.RRException;
import com.gdufe.firesafe.model.constants.DeviceAvailableConstant;
import com.gdufe.firesafe.model.constants.RoleConstant;
import com.gdufe.firesafe.model.dto.DeviceDTO;
import com.gdufe.firesafe.model.entity.*;
import com.gdufe.firesafe.model.enums.DeviceTypeEnum;
import com.gdufe.firesafe.model.vo.DeviceVO;
import com.gdufe.firesafe.service.DeviceService;
import com.gdufe.firesafe.service.HouseService;
import com.gdufe.firesafe.service.InspectorService;
import com.gdufe.firesafe.service.OwnerService;
import com.gdufe.firesafe.utils.PageUtils;
import com.gdufe.firesafe.utils.Query;
import com.gdufe.firesafe.utils.TokenUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Service("deviceService")
public class DeviceServiceImpl extends ServiceImpl<DeviceDao, DeviceEntity> implements DeviceService {
    @Resource
    private HouseService houseService;
    @Resource
    private InspectorService inspectorService;
    @Resource
    private OwnerService ownerService;
    @Resource
    private DeviceService deviceService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        LambdaQueryWrapper<DeviceEntity> queryWrapper = new LambdaQueryWrapper<>();
        //获取用户角色，如果是检查员，就要查询检查员负责的楼栋的房屋设备
        UserEntity currentUser = TokenUtils.getCurrentUser();
        if (RoleConstant.INSPECTOR.equals(currentUser.getRole())) {
            InspectorEntity inspector = inspectorService.getById(currentUser.getRoleId());
            queryWrapper.eq(DeviceEntity::getBuildingId, inspector.getBuildingId());
        }
        //拼查询条件
        String key = (String) params.get("key");
        if(StrUtil.isNotBlank(key)) {
            //设备类型
            Integer deviceTypeCode;
            //在枚举中寻找desc包含key的第一个枚举，获得它的code数字，寻找不到就赋值null
            deviceTypeCode = Arrays.stream(DeviceTypeEnum.values())
                    .filter(typeEnum -> typeEnum.getDescription().contains(key))
                    .findFirst()
                    .map(DeviceTypeEnum::getCode)
                    .orElse(null);
            //设备房屋地址
            List<HouseEntity> houseList = houseService.lambdaQuery().like(HouseEntity::getAddress, key).list();
            List<Integer> deviceIds = houseList.stream().flatMap(house ->
                    Stream.of(house.getFireExtinguisherId(), house.getSmokeDetectorId())
            ).collect(Collectors.toList());
            //是否可用
            Boolean available;
            if (DeviceAvailableConstant.AVAILABLE.equals(key)) {
                available = true;
            } else if (DeviceAvailableConstant.UNAVAILABLE.equals(key)) {
                available = false;
            } else {
                available = null;
            }
            //拼接
            queryWrapper.and(wrapper ->
                    wrapper.eq(DeviceEntity::getId, key)
                            .or().like(DeviceEntity::getModel, key)
                            .or().like(DeviceEntity::getManufacturer, key)
                            .or().like(DeviceEntity::getPurchaseDate, key)
                            .or().like(DeviceEntity::getExpireDate, key)
                            .or().like(DeviceEntity::getLastInspectionDate, key)
                            .or().like(DeviceEntity::getNote, key)
                            .or().in(!deviceIds.isEmpty(), DeviceEntity::getId, deviceIds)
                            .or().eq(DeviceEntity::getType, deviceTypeCode)
                            .or().eq(available != null, DeviceEntity::getAvailable, available)
            );
        }
        IPage<DeviceEntity> page = this.page(
                new Query<DeviceEntity>().getPage(params),
                queryWrapper
        );
        //entity转vo
        List<DeviceVO> deviceVOS = page.getRecords().stream().map((deviceEntity -> DeviceVO.entityToVO(deviceEntity, houseService))).collect(Collectors.toList());
        IPage<DeviceVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        voPage.setRecords(deviceVOS);
        voPage.setPages(page.getPages());
        return new PageUtils(voPage);
    }

    @Override
    public void validateAddOrUpdate(DeviceDTO deviceDTO, boolean add) {
        //获取属性
        List<Integer> selectedHouse = deviceDTO.getSelectedHouse();
        if (selectedHouse.size() != 3) {
            throw new RRException("数据输入不合法");
        }
        Integer houseId = selectedHouse.get(2);
        Integer type = deviceDTO.getType();
        Date expireDate = deviceDTO.getExpireDate();

        // 校验不为空
        if(houseId == null) {
            throw new RRException("房屋id不能为空");
        }
        if (add) {
            if (type == null) {
                throw new RRException("设备类型不能为空");
            }
            if (expireDate == null) {
                throw new RRException("设备到期时间不能为空");
            }
        }

        //校验houseId
        if (houseId <= 0) {
            throw new RRException("房屋id不合法");
        }
        if (houseService.getById(houseId) == null) {
            throw new RRException("房屋不存在");
        }
        //校验type
        if (DeviceTypeEnum.getEnumByCode(type) == null) {
            throw new RRException("设备类型不合法");
        }
    }

    @Transactional
    @Override
    public void addDevice(DeviceDTO deviceDTO) {
        DeviceEntity device = deviceDTO.toEntity();
        //新增设备
        this.save(device);
        //设置房屋对应设备id
        houseService.setDeviceIdWithDevice(device);
    }

    @Transactional
    @Override
    public void updateDevice(DeviceDTO deviceDTO) {
        DeviceEntity device = deviceDTO.toEntity();
        //查询旧的设备数据
        DeviceEntity oldDevice = this.getById(deviceDTO.getId());
        //如果设备所属房屋有改动那也要改动房屋的
        if (device.getHouseId() != null &&
                !oldDevice.getHouseId().equals(device.getHouseId())) {
            houseService.setDeviceIdWithDevice(device);
        }
        //更新设备
        this.updateById(device);
    }

    @Override
    public List<DeviceVO> getOwnerDevice() {
        UserEntity currentUser = TokenUtils.getCurrentUser();
        OwnerEntity owner = ownerService.getById(currentUser.getRoleId());
        HouseEntity house = houseService.getById(owner.getHouseId());
        DeviceEntity extinguisher = deviceService.getById(house.getFireExtinguisherId());
        DeviceEntity smokeDetector = deviceService.getById(house.getSmokeDetectorId());
        DeviceVO extinguisherVO = DeviceVO.entityToVO(extinguisher, house.getAddress());
        DeviceVO smokeDetectorVO = DeviceVO.entityToVO(smokeDetector, house.getAddress());
        return Arrays.asList(extinguisherVO, smokeDetectorVO);
    }

}
